home *** CD-ROM | disk | FTP | other *** search
- boolean
- fgsenddata (zdata, cdata)
- char *zdata;
- int cdata;
- {
- char *z;
- int itt, iseg, csize;
- unsigned short icheck;
-
- itt = DATA;
- csize = iGremote_packsize;
- iseg = iGremote_segsize + 1;
-
- if (cdata < iGremote_packsize)
- {
- /* If the remote packet size is larger than 64, the default, we
- can assume they can handle a smaller packet as well, which
- will be more efficient to send. */
- if (iGremote_packsize > 64)
- {
- /* The packet size is 1 << (iseg + 4). */
- iseg = 1;
- csize = 32;
- while (csize < cdata)
- {
- csize <<= 1;
- ++iseg;
- }
- }
-
- if (csize != cdata)
- {
- int cshort;
-
- /* We have to move the data within the packet,
- unfortunately. It only happens once per file transfer.
- It would also be nice if we computed the checksum as we
- move. We zero out the unused bytes. */
- itt = SHORTDATA;
- cshort = csize - cdata;
- if (cshort <= 127)
- {
- memmove (zdata + 1, zdata, cdata);
- zdata[0] = (char) cshort;
- memset (zdata + cdata + 1, 0, cshort - 1);
- }
- else
- {
- memmove (zdata + 2, zdata, cdata);
- zdata[0] = (char) (0x80 | (cshort & 0x7f));
- zdata[1] = (char) (cshort >> 7);
- memset (zdata + cdata + 2, 0, cshort - 2);
- }
- }
- }
-
- z = zdata - CFRAMELEN;
-
- z[IFRAME_DLE] = DLE;
- z[IFRAME_K] = (char) iseg;
-
- icheck = (unsigned short) igchecksum (zdata, csize);
-
- /* Wait until there is room in the receiver's window for us to send
- the packet. We do this now so that we send the correct value for
- the last packet received. Note that if iGsendseq ==
- iGremote_ack, this means that the sequence numbers are actually 8
- apart, since the packet could not have been acknowledged before
- it was sent; this can happen when the window size is 7. */
- while (iGsendseq == iGremote_ack
- || CSEQDIFF (iGsendseq, iGremote_ack) > iGremote_winsize)
- {
- if (! fgwait_for_packet (TRUE, cGtimeout, cGretries))
- return FALSE;
- }
-
- /* Ack all packets up to the next one, since the UUCP protocol
- requires that all packets be acked in order. */
- while (CSEQDIFF (iGrecseq, iGlocal_ack) > 1)
- {
- iGlocal_ack = INEXTSEQ (iGlocal_ack);
- if (! fgsend_control (RR, iGlocal_ack))
- return FALSE;
- }
- iGlocal_ack = iGrecseq;
-
- z[IFRAME_CONTROL] = (char) ((itt << 6) | (iGsendseq << 3) | iGrecseq);
-
- iGsendseq = INEXTSEQ (iGsendseq);
-
- icheck = ((unsigned short)
- ((0xaaaa - (icheck ^ (z[IFRAME_CONTROL] & 0xff))) & 0xffff));
- z[IFRAME_CHECKLOW] = (char) (icheck & 0xff);
- z[IFRAME_CHECKHIGH] = (char) (icheck >> 8);
-
- z[IFRAME_XOR] = (char) (z[IFRAME_K] ^ z[IFRAME_CHECKLOW]
- ^ z[IFRAME_CHECKHIGH] ^ z[IFRAME_CONTROL]);
-
- /* If we're waiting for acks of retransmitted packets, then don't
- send this packet yet. The other side may not be ready for it
- yet. Instead, code in fggot_ack will send the outstanding
- packets when an ack is received. */
- if (iGretransmit_seq != -1)
- return TRUE;
-
- return fsend_data (z, CFRAMELEN + csize, TRUE);
- }
-
-